package cn.wokoba.service.dcc;

import com.alibaba.nacos.api.config.listener.Listener;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.yaml.snakeyaml.Yaml;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.Executor;
import java.util.function.Consumer;

@Slf4j
@Service
@ToString
public class DccService implements Listener {

    /**
     * 降级开关 0关闭、1开启
     */
    private Integer downgradeSwitch = 0;

    private Integer cutRange = 100;

    private List<String> scBlacklist = List.of("");

    public boolean isDowngradeSwitch() {
        return "1".equals(downgradeSwitch.toString());
    }

    public boolean isCutRange(String userId) {
        // 计算哈希码的绝对值
        int hashCode = Math.abs(userId.hashCode());

        // 获取最后两位
        int lastTwoDigits = hashCode % 100;

        // 判断是否在切量范围内
        return lastTwoDigits <= cutRange;
    }

    @Override
    public Executor getExecutor() {
        return null;
    }

    @Override
    public void receiveConfigInfo(String content) {
        log.info("动态配置变更:{}", content);
        setContent(content);
    }

    public void setContent(String content) {
        Yaml yaml = new Yaml();
        Map<String, Object> configMap = yaml.load(content);

        // 调用通用方法
        setConfigValue(configMap, "downgradeSwitch", Integer.class, value -> downgradeSwitch = value);
        setConfigValue(configMap, "cutRange", Integer.class, value -> cutRange = value);
        setConfigValue(configMap, "scBlacklist", List.class, value -> scBlacklist = (List<String>) value);
    }

    private <T> void setConfigValue(Map<String, Object> configMap, String key, Class<T> targetType, Consumer<T> setter) {
        Optional.ofNullable(configMap.get(key))
                .filter(targetType::isInstance)  // 检查类型
                .map(targetType::cast)           // 转换为目标类型
                .ifPresent(setter);              // 调用 setter 函数
    }

    public boolean isSCBlackIntercept(String source, String channel) {
        return scBlacklist.contains(source + channel);
    }
}
